package express

import (
	"bytes"
	"context"
	"embed"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"sale-admin/config"
	"sale-admin/config/mysql"
	"sale-admin/internal/dao"
	"strings"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/logx"
	"github.com/samber/lo"
	"github.com/xuri/excelize/v2"
)

var ExpressCompanyMap = make(map[string]string)

//go:embed file/*
var expressFile embed.FS

// 加载快递公司
func init() {
	fileBytes, err := expressFile.ReadFile("file/company.xlsx")
	if err != nil {
		logx.Fatal(context.Background(), "无法读取通知文本")
	}
	fileReader := bytes.NewReader(fileBytes)
	f, err := excelize.OpenReader(fileReader)
	if err != nil {
		logx.Fatal(context.Background(), "读取excel通知失败")
	}
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	// 获取 Sheet1 上所有单元格
	rows, err := f.GetRows("快递100快递公司编码表")
	if err != nil {
		fmt.Println(err)
		return
	}
	for index, row := range rows {
		if index > 1 {
			if len(row) >= 3 {
				ExpressCompanyMap[row[1]] = row[0]
			}
		}
	}
}

type Express struct{}

// ExpressCompany 快递公司编码
// 此编码为快递100的编码
func (Express) Company(
	ctx context.Context,
	companyKeyword string,
) map[string]string {
	list := map[string]string{}
	for code, company := range ExpressCompanyMap {
		if strings.Contains(company, companyKeyword) {
			list[code] = company
		}
	}
	return list
}

// SetShipmentInfo 设置物流信息
func (Express) SetShipmentInfo(
	ctx context.Context,
	outTradeNO string,
	expressCom string, // 快递公司
	expressNum string, // 快递编号
) error {
	if _, ok := ExpressCompanyMap[expressCom]; !ok {
		return errorx.New("无效的快递公司", -1)
	}
	salt := lo.RandomString(8, lo.AlphanumericCharset)
	success := dao.OrderShipmentInfo{}.Set(ctx, mysql.NewDB(), outTradeNO, expressCom, expressNum, salt)
	if !success {
		return errorx.New("设置快递信息失败", -1)
	}
	err := Express{}.setShipmentInfoHook(ctx, expressCom, expressNum, salt)
	return err
}

type KD100Rsp struct {
	Result     bool   `json:"result"`
	ReturnCode string `json:"returnCode"`
	Message    string `json:"message"`
}

// setShipmentInfoHook 设置物流信息回调
func (Express) setShipmentInfoHook(ctx context.Context, expressCom, expressNum, salt string) error {
	// kuaidi100默认不支持https
	callbackURL := strings.Replace(config.Config.BaseUrl, "https://", "http://", 1) + "/public/kuaidi100/shipping-tracking"
	return kuaidi100Sub("TYfcSIUJ4687", expressCom, expressNum, callbackURL, salt)
}

func kuaidi100Sub(key string, com, num string, callbackURL, salt string) error {
	// 请求体参数
	param := map[string]interface{}{
		"company": com, // 快递公司编码
		"number":  num, // 快递单号
		"key":     key,
		"parameters": map[string]string{
			"callbackurl": callbackURL, // 回调地址
			"salt":        salt,
		},
	}

	paramJSON, _ := json.Marshal(param)

	form := url.Values{}
	form.Add("schema", "json")
	form.Add("param", string(paramJSON))

	resp, err := http.PostForm("https://poll.kuaidi100.com/poll", form)
	if err != nil {
		return errorx.New("订阅物流消息失败:"+err.Error(), -1)
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)

	// 订阅物流信息
	var rsp KD100Rsp
	json.Unmarshal(body, &rsp)
	if rsp.ReturnCode != "200" {
		return errorx.New("订阅物流消息失败:"+rsp.Message, -1)
	}
	return nil
}
